<template>
  <div class="dialog-container">
    <el-dialog :visible.sync="showAuthorize" width="90%" title="授权" :before-close="handleClose">
      <el-row :style="{height: contentHeight}" class="content-container">
        <el-col :span="7" class="content-left">
          <!-- 树 -->
          <el-tree ref="menuTreeRef" node-key="id" :data="menuTree" :props="defaultProps" :check-strictly="true"
            :default-checked-keys="defaultCheckMenuIds" show-checkbox :default-expand-all="true"
            :filter-node-method="filterNode" @check="checkData" @node-click="getNodeData" :expand-on-click-node="false"
            class="filter-tree" style="overflow: auto" highlight-current />
        </el-col>
        <el-col :span="16" class="content-right">
          <api-list ref="apiRef" :roleId="roleId" />
        </el-col>
      </el-row>
      <div slot="footer" align="center">
        <el-button @click="handleClose" type="danger">关 闭</el-button>
        <el-button @click="handleSave" type="primary" :disabled="btnDisabled">保 存</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
  import {
    getAuthMenuTree
  } from '@/api/sys/menu/index';
  import {
    authorizeMenu
  } from '@/api/sys/role/index'

  import * as common from '@/utils/base/common'

  /* 组件 */
  import apiList from './api-list'

  export default {
    /* 已有用户 */
    name: '',
    data() {
      return {
        contentHeight: parseInt(parseInt(document.documentElement.clientHeight)) / 2 + 'px',

        /* 部门树 */
        listLoading: false,
        menuTree: [],
        defaultProps: {
          children: 'children',
          label: 'name'
        }, // 配置选项

        defaultCheckMenuIds: [], // 默认选中

        btnDisabled: false, //按钮禁用状态
      }
    },
    components: {
      apiList
    },
    props: ['showAuthorize', 'roleId'],
    created() {
      this.initData()
    },
    updated() {
      // 给多选树设置默认值
      this.$refs.menuTreeRef.setCheckedKeys(this.defaultCheckMenuIds)
    },
    methods: {

      initData() {
        this.resetData()
        this.getList()
      },

      getList() {
        this.listLoading = true;
        getAuthMenuTree(this.roleId).then(response => {
          this.listLoading = false;
          this.menuTree = response.data.menuTree
          this.defaultCheckMenuIds = response.data.checkMenuIds
        }).catch(err => {
          this.listLoading = false;
          common.message(this, 'error', 2, '调用接口失败!')
          console.error(err)
        })
      },

      /**
       * 当复选框被点击的时候触发
       *  共两个参数，依次为：
       * @param {Object} node     树目前的选中状态对象，包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性
       * @param {Object} checkedNodes   传递给 data 属性的数组中该节点所对应的对象
       */
      checkData(node, checkedNodes) {
        // 用于：父子节点严格互不关联时，父节点勾选变化时通知子节点同步变化，实现单向关联。
        let selected = checkedNodes.checkedKeys.indexOf(node.id) // 返回-1表示未选中父节点

        // 选中父级节点
        if (selected !== -1) {
          // 子节点只要被选中父节点就被选中
          this.selectedParent(node)
          // 统一处理子节点为相同的勾选状态
          this.uniteChildSame(node, true)
        } else {
          // 未选中 处理子节点全部未选中
          if (node.children.length !== 0) {
            this.uniteChildSame(node, false)
          }
        }
      },

      /**
       * 统一处理子节点为相同的勾选状态
       * @param {Object} treeList
       * @param {Object} isSelected
       */
      uniteChildSame(treeList, isSelected) {
        this.$refs.menuTreeRef.setChecked(treeList.id, isSelected)
        for (let i = 0; i < treeList.children.length; i++) {
          this.uniteChildSame(treeList.children[i], isSelected)
        }
      },

      /**
       * 统一处理父节点为选中
       */
      selectedParent(node) {
        let currentNode = this.$refs.menuTreeRef.getNode(node)
        if (currentNode.parent.key !== undefined) {
          this.$refs.menuTreeRef.setChecked(currentNode.parent, true)
          this.selectedParent(currentNode.parent)
        }
      },


      /**
       * 点击保存按钮
       */
      handleSave() {
        // 若节点可被选择（即 show-checkbox 为 true），则返回目前被选中的节点的 key 所组成的数组
        let menuIds = this.$refs.menuTreeRef.getCheckedKeys()

        let myData = {
          roleId: this.roleId,
          menuIds: menuIds
        }
        authorizeMenu(myData).then(response => {
          if (response.code === 200) {
            common.message(this, 'success', 2, '授权成功!')
            this.handleClose()
          } else {
            common.tips(this, response.message)
          }
        }).catch(err => {
          common.message(this, 'error', 2, '授权失败!')
          console.error(err)
        })
      },


      // 节点被点击时, 获取该节点数据
      getNodeData(data) {
        if (data.pid != '-1') {
          this.$refs.apiRef.initData(data.id)
        } else {
          this.$refs.apiRef.resetData()
        }
      },

      // 对树节点进行筛选时执行的方法，返回 true 表示这个节点可以显示，返回 false 则表示这个节点会被隐藏
      filterNode(value, data) {
        if (!value) return true;
        return data.name.indexOf(value) !== -1;
      },

      resetData() {
        this.defaultCheckMenuIds = []
      },

      handleClose() {
        this.resetData()
        this.$emit('closeDialog') // 向父组件发送关闭事件
      },

    }
  }
</script>

<style lang="scss" scoped>
  @import "~@/styles/tree-list.css";

  /* 弹出框容器 */
  .dialog-container {
    width: 100%;
    height: 100%;
  }

  .dict-list {
    padding: 0;
    margin: 0;
    list-style: none;
  }

  .dict-list-item {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 50px;
    margin: 10px;
    cursor: pointer;
  }

  .unselect {
    background: #e8f3fe;
    color: #7dbcfc;
  }

  .select {
    background: #409EFF;
    color: #FFFFFF;
  }
</style>
